package xyz.jcat.sco.admin.oauth2.server.auth;

import org.springframework.http.HttpMethod;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import xyz.jcat.common.util.StringUtils;
import xyz.jcat.common.web.RespCodeMsg;
import xyz.jcat.common.web.RespException;
import xyz.jcat.sco.common.AuthenticationRequestException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class UserAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {

    private static final String PROCESSES_URL = "/admin/user/login";
    private static final String PARAMETER_NAME_USERNAME = "username";
    private static final String PARAMETER_NAME_PASSWORD = "password";
    private static final String PARAMETER_NAME_CAPTCHA = "captcha";

    public UserAuthenticationProcessingFilter() {
        super(PROCESSES_URL);
    }

    protected String getRequiredParameter(HttpServletRequest request, String name) {
        String value = request.getParameter(name);
        if(StringUtils.isBlank(value)) {
            throw new AuthenticationRequestException("Required parameter is blank",
                    new RespException(RespCodeMsg.REQUEST_PARAMETER_ERROR, "参数不能为空:"+name));
        }
        return value;
    }

    protected void checkRequestMethod(HttpServletRequest request, HttpMethod httpMethod) {
        if(!httpMethod.matches(request.getMethod())) {
            throw new AuthenticationRequestException("Request method error: "+request.getMethod(),
                    new RespException(RespCodeMsg.METHOD_NOT_SUPPORTED));
        }
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        checkRequestMethod(request, HttpMethod.POST);
        UserAuthenticationToken userAuthenticationToken = getUserAuthenticationToken(request);
        userAuthenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(userAuthenticationToken);
    }

    private UserAuthenticationToken getUserAuthenticationToken(HttpServletRequest request) {
        return new UserAuthenticationToken(
                getRequiredParameter(request, PARAMETER_NAME_USERNAME),
                getRequiredParameter(request, PARAMETER_NAME_PASSWORD),
                getRequiredParameter(request, PARAMETER_NAME_CAPTCHA));
    }

}
